﻿#include <linux/module.h>  
#include <linux/fs.h>  
#include <linux/cdev.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/slab.h>  
  
#define DEVICE_NAME "CEBSS_sr501"
#define CLASS_NAME  "sr501_gpio_pin"  
#define YOUR_GPIO_NUMBER 115
  
struct gpio_pin_dev {  
    struct cdev cdev;  
    unsigned int gpio;  
};  
  
static dev_t first_dev;  
static struct class *gpio_pin_class;
static struct gpio_pin_dev *dev;
  
static int gpio_pin_open(struct inode *inode, struct file *file)  
{  
    struct gpio_pin_dev *dev = container_of(inode->i_cdev, struct gpio_pin_dev, cdev);  
    int ret;  
  
    ret = gpio_request(dev->gpio, DEVICE_NAME);  
    if (ret) {  
        printk(KERN_ERR "%s: gpio_request failed\n", DEVICE_NAME);  
        return ret;  
    }  
  
    ret = gpio_direction_input(dev->gpio);  
    if (ret) {  
        printk(KERN_ERR "%s: gpio_direction_input failed\n", DEVICE_NAME);  
        gpio_free(dev->gpio);  
        return ret;  
    }  
  
    file->private_data = dev;  
    return 0;
}  
  
static int gpio_pin_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)  
{  
    dev = file->private_data;  
    int value;  
  
    value = gpio_get_value(dev->gpio);  
    if (copy_to_user(buf, &value, sizeof(value))) {  
        printk(KERN_ERR "%s: copy_to_user failed\n", DEVICE_NAME);  
        return -EFAULT;  
    }  
  
    return sizeof(value);   
}  
  
static int gpio_pin_release(struct inode *inode, struct file *file)  
{  
    struct gpio_pin_dev *dev = file->private_data;  
  
    gpio_free(dev->gpio);  
    return 0;  
}  
  
static const struct file_operations gpio_pin_fops = {  
    .owner = THIS_MODULE,  
    .open = gpio_pin_open,  
    .read = gpio_pin_read,  
    .release = gpio_pin_release,  
    // ... 可以添加其他操作 ...  
};  
  
static int __init gpio_pin_init(void)  
{  
    int ret;
    // 分配设备号  
    ret = alloc_chrdev_region(&first_dev, 0, 1, DEVICE_NAME);  
    if (ret < 0) {  
        printk(KERN_ERR "%s: alloc_chrdev_region failed\n", DEVICE_NAME);  
        return ret;  
    }  
  
    // 初始化设备结构体  
    dev = kzalloc(sizeof(struct gpio_pin_dev), GFP_KERNEL);  
    if (!dev) {  
        printk(KERN_ERR "%s: kzalloc failed\n", DEVICE_NAME);  
        unregister_chrdev_region(first_dev, 1);  
        return -ENOMEM;  
    }  
  
    // 设置GPIO引脚编号  
    dev->gpio = YOUR_GPIO_NUMBER;  
    dev->cdev.owner = THIS_MODULE;  
    dev->cdev.ops = &gpio_pin_fops;  
  
    // 注册字符设备  
    cdev_init(&dev->cdev, &gpio_pin_fops);
  
    ret = cdev_add(&dev->cdev, first_dev, 1);  
    if (ret) {  
        printk(KERN_ERR "%s: cdev_add failed\n", DEVICE_NAME);  
        kfree(dev);  
        unregister_chrdev_region(first_dev, 1);  
        return ret;  
    }  
  
    // 创建设备类  
    gpio_pin_class = class_create(THIS_MODULE, CLASS_NAME);  
    if (IS_ERR(gpio_pin_class)) {  
        printk(KERN_ERR "%s: class_create failed\n", DEVICE_NAME);  
        cdev_del(&dev->cdev);  
        kfree(dev);  
        unregister_chrdev_region(first_dev, 1);  
        return PTR_ERR(gpio_pin_class);  
    }  
  
    // 创建设备节点  
    device_create(gpio_pin_class, NULL, first_dev, NULL, DEVICE_NAME);  
  
    printk(KERN_INFO "%s: Device created with major %d and minor %d\n",  
           DEVICE_NAME, MAJOR(first_dev), MINOR(first_dev));  
  
    return 0;  
}
  
static void __exit gpio_pin_exit(void)  
{  
    dev_t devno = MKDEV(MAJOR(first_dev), 0);
    // 删除设备节点  
    device_destroy(gpio_pin_class, devno);  
  
    // 注销字符设备  
    cdev_del(&dev->cdev);  
  
    // 销毁设备类  
    class_destroy(gpio_pin_class);  
  
    // 释放设备号  
    unregister_chrdev_region(devno, 1);  
  
    // 释放设备结构体内存  
    kfree(dev);  
  
    printk(KERN_INFO "gpio_pin_exit: Module unloaded\n");  
}  
  
module_init(gpio_pin_init);  
module_exit(gpio_pin_exit);  
  
MODULE_LICENSE("GPL");
